package com.zzy.controller;

import com.alibaba.fastjson.JSONObject;
import com.zzy.model.FlowAudit;
import com.zzy.model.FlowStep;
import com.zzy.model.Leave;
import com.zzy.model.User;
import com.zzy.service.*;
import com.zzy.util.AjaxMsg;
import com.zzy.util.StatusCode;
import com.zzy.util.UtilJson;
import com.zzy.util.UtilUser;
import com.zzy.util.activiti.ProcessInstanceDiagramCmd;
import com.zzy.util.activiti.Util_Diagrams;
import org.activiti.engine.ProcessEngine;
import org.activiti.engine.RepositoryService;
import org.activiti.engine.RuntimeService;
import org.activiti.engine.TaskService;
import org.activiti.engine.history.HistoricActivityInstance;
import org.activiti.engine.history.HistoricProcessInstance;
import org.activiti.engine.history.HistoricTaskInstance;
import org.activiti.engine.history.HistoricVariableInstance;
import org.activiti.engine.impl.RepositoryServiceImpl;
import org.activiti.engine.impl.cmd.GetDeploymentProcessDiagramCmd;
import org.activiti.engine.impl.interceptor.Command;
import org.activiti.engine.impl.pvm.process.ActivityImpl;
import org.activiti.engine.impl.pvm.process.ProcessDefinitionImpl;
import org.activiti.engine.impl.task.TaskDefinition;
import org.activiti.engine.repository.ProcessDefinition;
import org.activiti.engine.runtime.ProcessInstance;
import org.activiti.engine.task.Task;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.servlet.ModelAndView;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import java.text.SimpleDateFormat;
import java.util.*;

/**
 * 测试会审
 */
@Controller
@RequestMapping("/flowhs")
public class FlowControllerHS {

    @Autowired
    private RepositoryServiceImpl repositoryServiceImpl;
    @Resource
    private ProcessEngine engine;

    @Autowired
    private ProcessEngine processEngine;

    @Autowired
    private UtilService utilService;

    @Autowired
    private UserService userService;

    /**
     *
     * 测试会审
     * 启动一个流程实例 josn 开启一个流程
     *  这里做两个模式
     * 模式一： 直接和表单绑定 (这样扩展性能不好)
     * 模式二：发起的时候，和表单绑定的话过于麻烦，这里把表单单独分离， 方便管理
     * 暂时按照模式二做，模式一 有时间在做处理
     */
    @RequestMapping("start")
    public void starttask(String flowDepId, HttpServletResponse response) {
        if(StringUtils.hasText(flowDepId)){
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");
            //1. 先启动流程实例
            RuntimeService service = engine.getRuntimeService();
            RepositoryService repositoryService = engine.getRepositoryService();
            RuntimeService runtimeService = engine.getRuntimeService();
            //第一个节点，设置了，发起人的 权限
            Map<String,Object> map = new HashMap<String, Object>();
            //设置下一 操作人为当前人
            User user = UtilUser.getSessionUser();
            map.put("user", user.getId());//流程发起人
            String TYPE_HS = "HS";//给每个流程分一个类 UtilFlow.TYPE_LEAVE
            map.put("businessType", TYPE_HS);//流程的 模块
            //service.startProcessInstanceById(flowId);
            //根据流程Key,查询以部署的流程定义
            String processModelKey = "HS_PRO";//流程图 process 的 ID UtilFlow.KEY_HS
            ProcessDefinition  pd = repositoryService.createProcessDefinitionQuery().processDefinitionKey(processModelKey).latestVersion().singleResult();
            if(pd==null){
                return;
            }
            String pdId = pd.getId() ;
            //获取全部环节。为流程环节动态添加处理
            List<Map<String, Object>> activities = getCandidateUserExpressions(pdId,repositoryServiceImpl);
            for (Map<String, Object> activity : activities){//循环了 每一个 node
                List<String> candidates = (List<String>) activity.get("candidates");
                if (candidates.isEmpty()){continue;}
                //map.put("state","y");
                for(String cand :candidates){//  找 每一个 node   candidate use..ma separated 的配置
                    System.out.println(cand);
                    String candidate = "";
                    if(cand.equals("all")){//说明这个节点是所有人都可以处理，也就是 上一个节点是谁这个节点 还是谁  注意和candidates.isEmpty()不是一个效果
                        candidate = user.getId();
                        map.put(cand, candidate );
                    }else {
                        //可以把这个设为 某个部门的 id ，根据部门的 id 查询全部人
                        //candidate = departService.getUserIDSByDepartID(user.getDepart());//这个方法暂时未完善
                        map.put(cand, candidate );//放个空字符串防止报错
                    }
                }
            }
            map.put("documentation","发起");//备注为发起
            // 到这 流程已经启动了
            runtimeService.startProcessInstanceById(pdId, map);
        }
        UtilJson.jsonPrintModel(AjaxMsg.returnAjaxMsg(StatusCode.SUCCESS, "success"),response);
    }

    /**取消发起*/
    @RequestMapping("unstart")
    public void unStart(String proId,String proName , String formId,HttpServletResponse response) {
        TaskService taskService = engine.getTaskService() ;
        RuntimeService runtimeService = engine.getRuntimeService();
        if(StringUtils.hasText(proId)){
            List<Task> curTasks = taskService.createTaskQuery().processInstanceId(proId).active().list();
            if (curTasks != null && curTasks.size() !=0){ //该流程实例未结束的
                runtimeService.deleteProcessInstance(proId,"");
            }
        }
        UtilJson.jsonPrintModel(AjaxMsg.returnAjaxMsg(StatusCode.SUCCESS, "取消成功"),response);
    }

    /**打开页面设计的窗口的*/
    @RequestMapping("open")
    public String openWin(HttpServletRequest request, String flowDepId,String flowName){
        Leave model = new Leave();//这个随便找个实体就行，主要是用公共的 属性字段，方便一次性 request.setAttribute
        model.setFlowDepId(flowDepId);//流程定义ID
        model.setFlowName(flowName);
        request.setAttribute("model",model);
        request.setAttribute("load",request.getParameter("load"));
        if(flowName.equals("请假审批")){//以后可以从数据库动态 配置
            return "page/leave/leave_detail";
        }else{
            return "redirect:index";
        }
    }



    /**
     * 完成当前节点，进入下一环节
     */
    @RequestMapping("complete")
    public void complete (
            @RequestParam(value = "state",required=false)final String state,//审核通过与否
            @RequestParam(value = "LastNodeName",required=false)final String LastNodeName,// 上一节点 的节点名称
            @RequestParam(value = "LastNodeId",required=false)final String LastNodeId,// 上一节点 的节点ID
            @RequestParam(value = "flowId",required=false)final String flowId,//流程ID
            @RequestParam(value = "flowDepId",required=false)final String flowDepId,//流程定义ID
            @RequestParam(value = "taskId",required=false)final String taskId,//任务ID
            HttpServletRequest request,
            HttpServletResponse response) {
        User user = UtilUser.getSessionUser();
        String auditUserId = user.getId();
        String auditUserName = user.getName();
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");
        String auditTime = sdf.format(new Date());

        TaskService taskService = engine.getTaskService();
        //测试 为 test1 提交 test2和test3 会审 zzy 终审
        String auditor0 = "40281e90673fc8ae01673fc9d3b40001,40281e90677209830167720cad8e0000";

        String auditor[] ={ "40281e90673fc8ae01673fc9d3b40001", "40281e90677209830167720cad8e0000"}; //假设传递过来 下一节点审核人的ID

        List list = new ArrayList();
        list.add( "40281e90673fc8ae01673fc9d3b40001");list.add("40281e90677209830167720cad8e0000");
        state.equals("y");//理论上 会审 只有审核通过
        //获取流程实例
        ProcessDefinition p01 = engine.getRepositoryService().createProcessDefinitionQuery().processDefinitionId(flowId).singleResult();
        //String flowName =  p01.getName() ;// 流程名字
        //2. 完成任务
        //List<Task> list = taskService.createTaskQuery().list();
        Map<String, Object> variables = new HashMap();
        //下一环节审核人

        variables.put("state",state);
        variables.put("per",auditUserId);//这里随机设置死一个 账户的ID
        variables.put("pers",list);
        variables.put("zzy","40281e90673fc8ae01673fca4f700003");//设置zzy为终审
        if(state.equals("y")){//这样写只能获取上个节点的审核意见
            variables.put("documentation","通过");
        }else{
            variables.put("documentation","退回");
        }

        taskService.complete( taskId , variables);


        //4. 更新对应表单的节点进度
        UtilJson.jsonPrintModel(AjaxMsg.returnAjaxMsg(StatusCode.SUCCESS, "success"),response);
    }


    /** 跳转到 进行中 */
    /** 获取待办 gird*/
    @RequestMapping("db/index")
    public String godb(HttpServletRequest request, HttpServletResponse response){
        return "page/flowhs/flow_db";
    }

    /** 获取待办 gird*/
    @RequestMapping("db/grid")
    @ResponseBody
    public void dbGrid( HttpServletRequest request, HttpServletResponse response){
        String businessType = "HS";//这里是请假的， 暂时不分类
        User user = UtilUser.getSessionUser();
        String userId = user.getId();
        TaskService service = engine.getTaskService();
        List<Task> list2 = service.createTaskQuery().processVariableValueEqualsIgnoreCase("businessType", businessType).list();
        //如果传递了 userid 则按照 userid 来 查询
        List<Task> list = new ArrayList<Task>();
        if(list2!=null && userId!=null && !"".equals(userId) ){
            for(Task task : list2){
                if(userId.equals(task.getAssignee())){
                    list.add(task);
                }
            }
        }


        Integer num = 0 ;
        String page =  request.getParameter("page");
        String rows =  request.getParameter("limit");
        Integer p = page == null ? 1 : Integer.valueOf(page);
        Integer r = rows == null ? 10 : Integer.valueOf(rows);




        List<Map> list1 = new ArrayList<Map>();//utilService.getListBySql(taskSql2);
        //num = taskList.size();
        if(!list.isEmpty()){
            for(Task task :list){
                Map map = new HashMap();
                map.put("flowId",task.getProcessInstanceId());
                map.put("nodeId",task.getTaskDefinitionKey());
                map.put("flowDepId",task.getProcessDefinitionId());
                map.put("flowDepId2",task.getProcessDefinitionId());//用于节点图
                map.put("taskId",task.getId());
                map.put("nodeName",task.getName());
                map.put("proName","会审审核");
                list1.add(map);
            }
        }

        UtilJson.jsonForLayerUI(list1,num,r,response);
    }


    /** 跳转到 进行中 */
    /** 获取待办 gird*/
    @RequestMapping("jxz/index")
    public String goJxz(HttpServletRequest request, HttpServletResponse response){
        RuntimeService service = engine.getRuntimeService();
        //service.startProcessInstanceById(id);
        return "page/flowhs/flow_jxz";
    }
    /** 获取 进行中 gird*/
    @RequestMapping("jxz/grid")
    @ResponseBody
    public void JxzGrid( HttpServletRequest request, HttpServletResponse response){
        TaskService taskService = engine.getTaskService();
        RuntimeService runtimeService = engine.getRuntimeService();
        User user = UtilUser.getSessionUser();
        //进行中的，根据用户的权限判断，
        String userId = user.getId();
        Integer num = 0 ;
        String page =  request.getParameter("page");
        String rows =  request.getParameter("limit");
        Integer p = page == null ? 1 : Integer.valueOf(page);
        Integer r = rows == null ? 10 : Integer.valueOf(rows);
        List  jsxList = new ArrayList ();


        // 进行中的 是当前人 参与过的 流程 还没有结束


        String flowType = "HS_PRO";//根据分类产
        //这个只获取 流程的信息，如果获取 task 信息
        // String sql = "SELECT  * FROM act_ru_execution WHERE PROC_DEF_ID_ like '%"+flowType+"%' AND ACT_ID_ is not null AND PROC_INST_ID_ in ( SELECT  DISTINCT EXECUTION_ID_ FROM act_ru_variable WHERE TEXT_ = '"+userId+"' )  GROUP BY PROC_INST_ID_ ORDER BY ID_ DESC ";


        //这个 sql 能获取到 流程走到的 最新节点 如果获取流程名字 ，在加上 act_re_procdef 表即可
        String sql2  = "SELECT a.PROC_INST_ID_  , a.PROC_DEF_ID_ , b.ID_ as task_id ,b.NAME_ ,b.TASK_DEF_KEY_ ,b.CREATE_TIME_ FROM " +
                "( " +
                "SELECT  * FROM act_ru_execution WHERE PROC_DEF_ID_ like '%"+flowType+"%' AND ACT_ID_ is not null AND PROC_INST_ID_ in ( SELECT  DISTINCT EXECUTION_ID_ FROM act_ru_variable WHERE TEXT_ = '"+userId+"' )  GROUP BY PROC_INST_ID_ ORDER BY ID_ DESC" +
                ") a " +
                "INNER JOIN ( SELECT  * FROM act_ru_task  WHERE PROC_DEF_ID_ like '%"+flowType+"%' GROUP BY PROC_INST_ID_ ORDER BY CREATE_TIME_ DESC ) b WHERE a.PROC_INST_ID_ = b.PROC_INST_ID_ ";



        // 流程的信息 和 task 信息
        List<Object[]> list0 = utilService.getListBySql(sql2);
        if(!list0.isEmpty()){
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");
            for(Object arr[] :list0){
                Map map = new HashMap();
                map.put("flowId",arr[0]);
                map.put("flowDepId",arr[1]);
                map.put("taskId",arr[2]);
                map.put("nodeName",arr[3]);
                map.put("nodeId",arr[4]);
                map.put("createTime",sdf.format((Date)arr[5]));
                jsxList.add(map);
            }
        }
        UtilJson.jsonForLayerUI(jsxList,num,r,response);
    }

    /** 跳转到 已完结 */
    @RequestMapping("history/index")
    public String goHistory( HttpServletRequest request, HttpServletResponse response){
        RuntimeService service = engine.getRuntimeService();
        List<HistoricProcessInstance> list =  engine.getHistoryService().createHistoricProcessInstanceQuery().list();

        //service.startProcessInstanceById(id);
        return "page/flowhs/flow_history";
    }
    /** 获取 已完结gird*/
    @RequestMapping("history/grid")
    @ResponseBody
    public void historyGird( HttpServletRequest request, HttpServletResponse response){
        User user = UtilUser.getSessionUser();
        String userId = user.getId();
        // finished() 标示已经完成的流程
        List<HistoricProcessInstance> list01 =  engine.getHistoryService().
                createHistoricProcessInstanceQuery().finished().variableValueLike("businessType","HS")
                .orderByProcessInstanceStartTime().asc().list();//查询到 会审的 所有结束的
        Integer num = 0 ;
        String page =  request.getParameter("page");
        String rows =  request.getParameter("limit");
        Integer p = page == null ? 1 : Integer.valueOf(page);
        Integer r = rows == null ? 10 : Integer.valueOf(rows);
        List listResult = new ArrayList();
        if(!list01.isEmpty()){
            num = list01.size();
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");
            for(HistoricProcessInstance h : list01 ){
                Map map = new HashMap();
                map.put("flowName","会审审核");
                map.put("flowId", h.getId());
                map.put("flowDepId",h.getProcessDefinitionId());
                map.put("startTime",sdf.format( h.getStartTime() ));
                map.put("endTime",sdf.format( h.getEndTime() ));
                listResult.add(map);
            }
        }



        UtilJson.jsonForLayerUI(listResult,num,r,response);


    }




    /** 跳转到 已完结 */
    @RequestMapping("time/line")
    public String goTimeLine( HttpServletRequest request, HttpServletResponse response){
        String flowDepId = request.getParameter("flowDepId");
        String flowId = request.getParameter("flowId");
        String flowName = request.getParameter("flowName");
        List resultList = new ArrayList();
        if(StringUtils.hasText(flowId)){

            //某一次流程执行了多少任务
            List<HistoricTaskInstance> list = processEngine.getHistoryService()
                    .createHistoricTaskInstanceQuery()
                    .processInstanceId(flowId).orderByHistoricTaskInstanceEndTime().asc()
                    .list();
            if (list != null && list.size() > 0) {
                SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");
                for (HistoricTaskInstance h : list) {
                    String name = h.getName();//name
                    String taskId = h.getId();//taskId
                    String flowDepId1 = h.getProcessDefinitionId();
                    String assignee = h.getAssignee();
                    String userName = userService.getByID(assignee).getName();
                    String startTime = sdf.format(h.getStartTime());
                    String endTime =sdf.format( h.getEndTime());
                    Map map = new HashMap();
                    map.put("name",name);
                    map.put("userName",userName);
                    map.put("startTime",startTime);
                    map.put("endTime",endTime);
                    map.put("taskId",taskId);
                    map.put("flowDepId",flowDepId1);
                    map.put("opinion",h.getDescription());//上个节点对本次的意见
                    resultList.add(map);
                }
            }
        }
        request.setAttribute("flowName",flowName);
        request.setAttribute("list",resultList);
        //某一次流程执行了多少步
        /*List<HistoricTaskInstance> list2 = processEngine.getHistoryService()
                .createHistoricTaskInstanceQuery()
                .processInstanceId(processInstanceId).orderByHistoricTaskInstanceEndTime().asc()
                .list();
        if (list2 != null && list2.size() > 0) {
            for (HistoricTaskInstance hti : list2) {
                System.out.print("taskId:" + hti.getId()+"，");
                System.out.print("name:" + hti.getName()+"，");
                System.out.print("pdId:" + hti.getProcessDefinitionId()+"，");
                System.out.print("assignee:" + hti.getAssignee()+"，");
            }
        }*/

        return "page/flowhs/flow_time_line";
    }
    /** 跳转到 已完结 */
    @RequestMapping("time/line/info")
    public void timeLine( HttpServletRequest request, HttpServletResponse response){
        String flowDepId = request.getParameter("flowDepId");
        String flowId = request.getParameter("flowId");
        Map map = new HashMap();
        UtilJson.jsonPrintModel(map,response);
    }



    /** 获取流程的环节信息*/
    public  List<Map<String,Object>> getCandidateUserExpressions(String processDefinitionId ,RepositoryServiceImpl repositoryService) {
        List<Map<String,Object>> result = new ArrayList<Map<String,Object>>();

        if(repositoryService == null) {return null;}
        //获取流程定义的所有环节
        ProcessDefinitionImpl processDefinitionImpl =  (ProcessDefinitionImpl)repositoryService .getDeployedProcessDefinition(processDefinitionId);

        List<ActivityImpl>  activitiList = processDefinitionImpl.getActivities();
        for(ActivityImpl act : activitiList){ //流程节点信息
            Map<String,Object> prop = act.getProperties();//节点属性
            String type = prop.get("type").toString();//节点类型
            if("userTask".equals(type)){
                Map<String,Object> map = new HashMap<String, Object>();
                TaskDefinition td = (TaskDefinition) prop.get("taskDefinition");//任务定义类
                List<String> candidates = getLingCandidates(td);//候选人列表
                map.put("activityId", act.getId());//节点id
                map.put("activityName", prop.get("name"));//节点属性
                map.put("candidates", candidates);//候选人用户表达式
                result.add(map);
            }
        }
        return result;
    }
    /**获取候选人列表*/
    public  List<String> getLingCandidates(TaskDefinition t){
        List<String> candidates = new ArrayList<String>();//候选人列表
        @SuppressWarnings("rawtypes")
        Set set = new HashSet();
        if(t.getCandidateUserIdExpressions().size() > 0){
            set = t.getCandidateUserIdExpressions();
        } else if(t.getCandidateGroupIdExpressions().size() > 0) {
            set = t.getCandidateGroupIdExpressions();
        }
        if(set.size() > 0){
            Object[] objs = set.toArray();
            for(Object obj : objs){
                if(obj != null){
                    String tmp = obj.toString();//格式为${xxx}
                    if(tmp.length() > 3){
                        candidates.add(tmp.substring(2, tmp.length()-1));
                    }
                }
            }
        } else if(t.getAssigneeExpression() != null){
            Object obj = t.getAssigneeExpression();
            if(obj != null){
                String tmp = obj.toString();
                if(tmp.length() > 3){
                    candidates.add(tmp.substring(2, tmp.length()-1));
                }
            }
        }
        return candidates;
    }




    /**
     * 查询历史流程实例
     */

    public void queryHistoricInstance() {
        List<HistoricProcessInstance> list = processEngine.getHistoryService()
                .createHistoricProcessInstanceQuery()
                .orderByProcessInstanceStartTime().asc()//排序
                .list();
        if (list != null && list.size() > 0) {
            for (HistoricProcessInstance hpi : list) {
                System.out.println("流程定义ID：" + hpi.getProcessDefinitionId());
                System.out.println("流程实例ID：" + hpi.getId());
                System.out.println("开始时间：" + hpi.getStartTime());
                System.out.println("结束时间：" + hpi.getEndTime());
                System.out.println("流程持续时间：" + hpi.getDurationInMillis());
                System.out.println("=======================================");
            }
        }
    }

    /**
     * 某一次流程执行了多少步
     */

    public void queryHistoricActivitiInstance() {
        String processInstanceId = "27501";
        List<HistoricActivityInstance> list = processEngine.getHistoryService()
                .createHistoricActivityInstanceQuery()
                .processInstanceId(processInstanceId)
                .list();
        if (list != null && list.size() > 0) {
            for (HistoricActivityInstance hai : list) {
                System.out.println(hai.getId());
                System.out.println("步骤ID：" + hai.getActivityId());
                System.out.println("步骤名称：" + hai.getActivityName());
                System.out.println("执行人：" + hai.getAssignee());
                System.out.println("====================================");
            }
        }
    }

    /**
     * 某一次流程的执行经历的多少任务
     */

    public void queryHistoricTask() {
        String processInstanceId = "27501";
        List<HistoricTaskInstance> list = processEngine.getHistoryService()
                .createHistoricTaskInstanceQuery()
                .processInstanceId(processInstanceId)
                .list();
        if (list != null && list.size() > 0) {
            for (HistoricTaskInstance hti : list) {
                System.out.print("taskId:" + hti.getId()+"，");
                System.out.print("name:" + hti.getName()+"，");
                System.out.print("pdId:" + hti.getProcessDefinitionId()+"，");
                System.out.print("assignee:" + hti.getAssignee()+"，");
            }
        }
    }

    /**
     * 某一次流程的执行时设置的流程变量
     */

    public void queryHistoricVariables() {
        String processInstanceId = "37501";
        List<HistoricVariableInstance> list = processEngine.getHistoryService()
                .createHistoricVariableInstanceQuery()
                .processInstanceId(processInstanceId)
                .list();
        if(list != null && list.size()>0){
            for(HistoricVariableInstance hvi : list){
                System.out.print("piId:"+hvi.getProcessInstanceId()+"，");
                System.out.print("variablesName:"+hvi.getVariableName()+"，");
                System.out.println("variablesValue:"+hvi.getValue()+";");
            }
        }
    }

}
